package com.adwszzy;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ScreenMatcher {

    //相似度最小值
    private static final double similarityMinimum = 0.6;
    private static final double newSimilarityMinimum = 0.65;
    private static final double suitSimilarityMinimum = 0.6;
    private static final double borderSimilarityMinimum = 0.3;
    public static boolean execFlag = true;
    private static boolean loadLib = true;
    private static void loadLib()  {
        if (loadLib) {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
            ConfigurationMaps.load();
            loadLib = false;
        }
    }
    public static void main(String[] args) throws AWTException {
        loadLib();
        Robot robot=new Robot();
//        Mat screenMat = getScreenShot(robot);
//            //2、根据cost匹配属性
//        System.out.println("2、根据cost匹配属性");
//        int cNumber = matchAndContrastThread(screenMat,similarityMinimum, Imgcodecs.imread(ConfigConstants.getC1Pic()), Imgcodecs.imread(ConfigConstants.getC3Pic()), Imgcodecs.imread(ConfigConstants.getC4Pic()));

        matchAndlockTheSoundSkeleton(robot);
        }

    public static void fuseTheSoundSkeleton() throws AWTException, InterruptedException{
        boolean hasNotConfirmTheTable = true;
        loadLib();
        Robot robot=new Robot();
        Mat screenMat = null;
        Mat template = null;
        try {
            while (execFlag) {
                screenMat = getScreenShot(robot);
                // 点击自动放入声骸，并点击合成
                template = Imgcodecs.imread(ConfigConstants.putButtonPic);
                matchAndPress(template,screenMat , robot, 0.2, 0.4);

                Mat template1 = Imgcodecs.imread(ConfigConstants.fuseButtonPic);
                matchAndPress(template1, screenMat, robot, 0.2, 0.4);
                template1.release();
                template.release();
                //判断是否有“高品质声骸”确认框，已经确认过一次就无需再判断
                Thread.sleep(200);
                if (hasNotConfirmTheTable) {
                    ScreenMatcher.matchAndCheckConfirmTable(robot);
                    hasNotConfirmTheTable = false;
                }
                //等待时间极长
                Thread.sleep(3500);
                //匹配图中的声骸并查看属性，锁定需要的
                screenMat.release();
                circleBorderDetection(robot);
                template.release();
                template1.release();
                screenMat.release();
                Thread.sleep(500);
            }



        }finally {
            // 清理
            if (screenMat!=null)screenMat.release();
            if (template!=null)template.release();
        }

    }
    public static void backPackMatcher() throws AWTException, InterruptedException {
        loadLib();
        Robot robot=new Robot();
        //初始查看主词条是否匹配 匹配则判断是否已经锁定，确保其锁定
        matchAndlockTheSoundSkeleton(robot);
        //循环 直到屏幕中没有匹配的区块，
        //匹配截屏中带有“新”的区块并点击
        while (execFlag) {
            Mat screenMat = null;
            Mat template = null;
            try {
            screenMat = getScreenShot(robot);
            // 匹配 “新” 标签，点击位置向下偏移
            template = Imgcodecs.imread(ConfigConstants.newPic);
            if (!matchAndPress(template, screenMat, robot, 0, 1)) {
                backPackLoop(robot);
                continue;
            }
            Thread.sleep(50);
            matchAndlockTheSoundSkeleton(robot);
            }finally {
                // 清理
                if (screenMat!=null)screenMat.release();
                if (template!=null)template.release();
            }

        }



        //查看主词条是否匹配
    }

    /**
     * 背包页面滚动
     * @param robot
     * @return
     */
    public static boolean backPackLoop(Robot robot) {
        loadLib();
        System.out.println("滚动");
        Mat src = getScreenShot(robot);
        Mat target = Imgcodecs.imread(ConfigConstants.infoPic);
        Mat outputImage = null;
        try {
            outputImage = new Mat(src.rows(), src.cols(), src.type());
            Imgproc.matchTemplate(src, target, outputImage, Imgproc.TM_CCOEFF_NORMED);

            // 获取匹配结果,查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
            Point matchLoc = result.maxLoc;
            double similarity = result.maxVal; //匹配度 低于0.9的不要
            if (similarity < newSimilarityMinimum) {
                System.out.println("匹配值为："+similarity+"，数值过低");
                return false;
            } else {
                if (robot != null) {//robot不为空，执行点击
                    int x = (int) Math.round(matchLoc.x + target.cols()+140); //小图大大图中的x坐标+增加偏移量
                    int y = (int) Math.round(matchLoc.y +440); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 执行鼠标左键点击
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int i = 0; i <= 550; i++) {
                        robot.mouseMove(x, y-i);
                        try {
                            Thread.sleep(5);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

                    //将查找到的结果标上框框
                    //Imgproc.rectangle(src,new Point(x,y),new Point(x+target.cols(),y+target.rows()),
                    //        new Scalar( 0, 0, 255),2);
                    //
                    ////5.显示结果
                    //HighGui.imshow("模板匹配", src);
                    //HighGui.waitKey();
                }
                return true;
            }
        } finally {
            if (outputImage != null) {
                outputImage.release();
            }
            src.release();
            target.release();
        }
    } /**
     * 匹配并点击确认框
     * @param robot
     * @return
     */
    public static boolean matchAndCheckConfirmTable(Robot robot) throws InterruptedException {
        loadLib();
        System.out.println("查看是否弹出确认框");
        Thread.sleep(200);
        Mat src = getScreenShot(robot);
        Mat target = Imgcodecs.imread(ConfigConstants.confirmTablePic);
        Mat outputImage = null;
        try {
            outputImage = new Mat(src.rows(), src.cols(), src.type());
            Imgproc.matchTemplate(src, target, outputImage, Imgproc.TM_CCOEFF_NORMED);

            // 获取匹配结果,查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
//            Point matchLoc = result.maxLoc;
            double similarity = result.maxVal; //匹配度 低于0.9的不要
            if (similarity < similarityMinimum) {
                System.out.println("匹配值为："+similarity+"，数值过低");
                return false;
            } else {
                Mat target1 = null;
                Mat target2 = null;
                try {
                    target1 = Imgcodecs.imread(ConfigConstants.confirmRedioPic);
                    target2 = Imgcodecs.imread(ConfigConstants.confirmButtonPic);
                    outputImage.release();
                    outputImage = new Mat(src.rows(), src.cols(), src.type());
                    Imgproc.matchTemplate(src, target1, outputImage, Imgproc.TM_CCOEFF_NORMED);
                    result = Core.minMaxLoc(outputImage);
                    int x = (int) Math.round(result.maxLoc.x+20 ); //小图大大图中的x坐标+增加偏移量
                    int y = (int) Math.round(result.maxLoc.y+20 ); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);
                    Thread.sleep(50);
                    // 执行鼠标左键点击
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                    Thread.sleep(50);
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                    outputImage.release();
                    outputImage = new Mat(src.rows(), src.cols(), src.type());
                    Imgproc.matchTemplate(src, target2, outputImage, Imgproc.TM_CCOEFF_NORMED);
                    result = Core.minMaxLoc(outputImage);
                    x = (int) Math.round(result.maxLoc.x+20); //小图大大图中的x坐标+增加偏移量
                    y = (int) Math.round(result.maxLoc.y+20); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);

                    Thread.sleep(50);
                    // 执行鼠标左键点击
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
//                        Thread.sleep(50);
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                    outputImage.release();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }finally {
                    if (target1!=null)target1.release();
                    if (target2!=null)target2.release();
                }
                return true;
            }
        } finally {
            if (outputImage != null) {
                outputImage.release();
            }
            src.release();
            target.release();
        }
    }
    /**
     * 匹配并锁定
     * @param robot
     * @throws AWTException
     */
    public static void matchAndlockTheSoundSkeleton(Robot robot) {
        loadLib();
        Mat screenMat = getScreenShot(robot);
        try {
//        // 1、匹配cost数
//        Mat template = Imgcodecs.imread(ConfigConstants.newPic);
//        //todo
//        matchAndPress(template, screenMat, robot, 0, 1);
        //2、根据cost匹配属性
        System.out.println("2、根据cost匹配属性");
        int cNumber = matchAndContrastThread(screenMat,similarityMinimum, Imgcodecs.imread(ConfigConstants.getC1Pic()), Imgcodecs.imread(ConfigConstants.getC3Pic()), Imgcodecs.imread(ConfigConstants.getC4Pic()));
        JSONObject priorityInfo = null;
        JSONArray attrArray ;
        String path = null;
        switch (cNumber) {
            case 0:
                path = ConfigConstants.getC1Path();
                priorityInfo = ConfigurationMaps.priorityInfo.getJSONObject("1c");
                break;
            case 1:
                path = ConfigConstants.getC3Path();
                priorityInfo = ConfigurationMaps.priorityInfo.getJSONObject("3c");
                break;
            case 2:
                path = ConfigConstants.getC4Path();
                priorityInfo = ConfigurationMaps.priorityInfo.getJSONObject("4c");
                break;
            default:
                System.out.println("cost数值识别失败");
                return;
        }
        //3、匹配套装
        String suit=matchSuit(screenMat);
            if (suit == null) {

                System.out.println("套装识别失败");
                return;
            }else{
                attrArray=priorityInfo.getJSONArray(suit);
                if (matchAttr(screenMat, attrArray, path)) {//匹配属性 如果返回true就锁定
                    //4、满足属性的点击锁定
                    matchAndPressTheLock(screenMat,robot,0.5,0.1);
                }
            }
        }finally {
            screenMat.release();
        }

    }
//    public static void lockTheSoundSkeleton(Robot robot) {
//
//    }
    public static String matchSuit(Mat src) {
        loadLib();
        JSONObject suit = ConfigurationMaps.suitInfo;
        String[] keys = suit.keySet().toArray(new String[0]);
        Mat[] targets = new Mat[keys.length];
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            targets[i] = Imgcodecs.imread(ConfigConstants.getSuitPath() + key);
        }
        System.out.println("套装识别");
        int matchIdx = matchAndContrastThread(src,suitSimilarityMinimum, targets);
        if (matchIdx == -1) {
            System.out.println("套装匹配失败");
            return null;
        } else {
            return suit.getString(keys[matchIdx]);
        }
    }
    public static boolean matchAttr(Mat src,JSONArray attrArray,String path) {
        loadLib();

//        for (int i = 0; i < attrArray.size(); i++) {
//            String key = attrArray.getString(i);
//            String pic = "";
//            if (path.equals(ConfigConstants.getC1Path();)) pic = ConfigurationMaps.c1Info.getString(key);
//            else if (path.equals(ConfigConstants.getC3Path())) pic = ConfigurationMaps.c3Info.getString(key);
//            else if (path.equals(ConfigConstants.getC4Path())) pic = ConfigurationMaps.c4Info.getString(key);
//            targets[i] = Imgcodecs.imread(path + pic);
//        }
        JSONObject jsonInfo=null;
        System.out.println(123);
        if (path.equals(ConfigConstants.getC1Path())) jsonInfo = ConfigurationMaps.c1Info;
            else if (path.equals(ConfigConstants.getC3Path())) jsonInfo = ConfigurationMaps.c3Info;
            else if (path.equals(ConfigConstants.getC4Path())) jsonInfo = ConfigurationMaps.c4Info;
        Mat[] targets = new Mat[jsonInfo.size()];
        int i=0;
        String keys[]=new String[jsonInfo.size()];
        for (String key:jsonInfo.keySet()) {
            keys[i] = key;
            targets[i++] = Imgcodecs.imread(path + jsonInfo.get(key));
        }

        int matchIdx = matchAndContrastThread(src,similarityMinimum, targets);
        if (matchIdx == -1) {
            System.out.println("右侧属性识别失败");
            return false;
        } else {
//            boolean found =false;
//            String[] attrs = attrArray.toArray(String.class);
//            for (String attr : attrs) {
//                if (attr.equals(keys[matchIdx])) {
//                    found = true;
//                    break;
//                }
//            }
            boolean found = Arrays.stream(attrArray.toArray(String.class))
                    .anyMatch(s -> s.equals(keys[matchIdx]));
            if (found) {
                System.out.println("匹配到了"+path+jsonInfo.get(keys[matchIdx])+"的套装");
                return true;
            } else {
                System.out.println("右侧属性不符合要求，跳过");
                return false;
            }

        }
    }

    public static Mat getScreenShot(Robot robot) {
        loadLib();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;
        Rectangle screenRect = new Rectangle(screenWidth, screenHeight);
        BufferedImage screenImageTemp = robot.createScreenCapture(screenRect);

        BufferedImage screenImage = new BufferedImage(screenImageTemp.getWidth(), screenImageTemp.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        screenImage.getGraphics().drawImage(screenImageTemp, 0, 0, null);
        // 将BufferedImage转换为Mat
//            Mat screenMat = ImageUtil.bufferedImageToMat(screenImage);
        return bufferedImageToMat(screenImage);
    }


    /**
     * 匹配并点击
     *
     * @param target
     * @param src
     * @param robot
     * @return
     */
    public static boolean matchAndPress(Mat target, Mat src, Robot robot, double offsetPercentageX, double offsetPercentageY) {
        loadLib();
        Mat outputImage = null;
        try {
            outputImage = new Mat(src.rows(), src.cols(), src.type());
            Imgproc.matchTemplate(src, target, outputImage, Imgproc.TM_CCOEFF_NORMED);

            // 获取匹配结果,查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
            Point matchLoc = result.maxLoc;
            double similarity = result.maxVal; //匹配度 低于0.9的不要
            if (similarity < newSimilarityMinimum) {
                System.out.println("匹配值为："+similarity+"，数值过低");
                return false;
            } else {
                if (robot != null) {//robot不为空，执行点击
                    System.out.println(target.rows());
                    System.out.println(target.cols());
                    int x = (int) Math.round(matchLoc.x + target.cols() * offsetPercentageX); //小图大大图中的x坐标+增加偏移量
                    int y = (int) Math.round(matchLoc.y + target.rows() * offsetPercentageY); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 执行鼠标左键点击
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

                    //将查找到的结果标上框框
                    //Imgproc.rectangle(src,new Point(x,y),new Point(x+target.cols(),y+target.rows()),
                    //        new Scalar( 0, 0, 255),2);
                    //
                    ////5.显示结果
                    //HighGui.imshow("模板匹配", src);
                    //HighGui.waitKey();
                }
                return true;
            }
        } finally {
            if (outputImage != null) {
                outputImage.release();
            }
            target.release();
        }
    }
    /**
     * 匹配并点击
     *
     * @param target
     * @param src
     * @param robot
     * @return
     */
    public static boolean matchAndPressTest(Mat target, Mat src, Robot robot, double offsetPercentageX, double offsetPercentageY) {
        loadLib();
        Mat outputImage = null;
        try {
            outputImage = new Mat(src.rows(), src.cols(), src.type());
            Imgproc.matchTemplate(src, target, outputImage, Imgproc.TM_CCOEFF_NORMED);

            // 获取匹配结果,查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
            Point matchLoc = result.maxLoc;
            double similarity = result.maxVal; //匹配度 低于0.9的不要
            if (similarity < 0.57) {
                System.out.println("匹配值为："+similarity+"，数值过低");
                return false;
            } else {
                if (robot != null) {//robot不为空，执行点击
                    System.out.println(target.rows());
                    System.out.println(target.cols());
                    int x = (int) Math.round(matchLoc.x); //小图大大图中的x坐标+增加偏移量
                    int y = (int) Math.round(matchLoc.y); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 执行鼠标左键点击
//                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
//                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

                    //将查找到的结果标上框框
//                    Imgproc.rectangle(src,new Point(x,y),new Point(x+target.cols(),y+target.rows()),
//                            new Scalar( 0, 0, 255),2);

                    //5.显示结果
//                    HighGui.imshow("模板匹配", src);
//                    HighGui.waitKey();
                }
                return true;
            }
        } finally {
            if (outputImage != null) {
                outputImage.release();
            }
            target.release();
        }
    }
    /**
     * 多条对比匹配并点击
     * 由于锁定与解锁图太像了
     * @param src
     * @param robot
     * @return
     */
    public static boolean matchAndPressTheLock( Mat src, Robot robot, double offsetPercentageX, double offsetPercentageY) {
        loadLib();
        Mat outputImage1 = null;
        Mat outputImage2 = null;
        Mat lockImg = null;
        Mat unlockImg = null;
        try {
            lockImg=Imgcodecs.imread(ConfigConstants.lockPic);
            unlockImg=Imgcodecs.imread(ConfigConstants.unlockPic);
            outputImage1 = new Mat(src.rows(), src.cols(), src.type());
            outputImage2 = new Mat(src.rows(), src.cols(), src.type());

            Imgproc.matchTemplate(src, unlockImg, outputImage1, Imgproc.TM_CCOEFF_NORMED);

            // 获取匹配结果,查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage1);
            Point matchLoc = result.maxLoc;
            double similarity = result.maxVal; //匹配度 低于0.9的不要
            if (similarity < similarityMinimum) {
                return false;
            } else {
                //如果锁定按钮比未锁定的按钮匹配值高，那可以认为声骸已经被锁定无需点击
                Imgproc.matchTemplate(src, lockImg, outputImage2, Imgproc.TM_CCOEFF_NORMED);
                Core.MinMaxLocResult lockresult = Core.minMaxLoc(outputImage2);
                if (similarity < lockresult.maxVal) {
                    return false;
                }
                if (robot != null) {//robot不为空，执行点击
                    System.out.println(unlockImg.rows());
                    System.out.println(unlockImg.cols());
                    int x = (int) Math.round(matchLoc.x + unlockImg.cols() * offsetPercentageX); //小图大大图中的x坐标+增加偏移量
                    int y = (int) Math.round(matchLoc.y + unlockImg.rows() * offsetPercentageY); //小图大大图中的y坐标
                    System.out.println(x + "," + y + " similarity: " + similarity);
                    robot.mouseMove(x, y);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 执行鼠标左键点击
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

                    //将查找到的结果标上框框
                    //Imgproc.rectangle(src,new Point(x,y),new Point(x+target.cols(),y+target.rows()),
                    //        new Scalar( 0, 0, 255),2);
                    //
                    ////5.显示结果
                    //HighGui.imshow("模板匹配", src);
                    //HighGui.waitKey();
                }
                return true;
            }
        } finally {
            if (outputImage1 != null) {
                outputImage1.release();
            }
            if (outputImage2 != null) {
                outputImage2.release();
            }
            if (lockImg != null) {
                lockImg.release();
            }
            if (unlockImg != null) {
                unlockImg.release();
            }
        }
    }

    /**
     * 基于 matchAndContrast 方法，使用线程缩短匹配时间
     * @param src
     * @param similarityMinimum
     * @param targets
     * @return
     */
    public static int matchAndContrastThread(Mat src,double similarityMinimum, Mat... targets) {
        loadLib();
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        try {
// 提交任务
            List<Future<Double>> futures = new ArrayList<>();
            Double[] doubles = new Double[targets.length];
            for (int i = 0; i < targets.length; i++) {
                Mat template = targets[i];
                int finalI = i;
                futures.add(executorService.submit(() -> {
                    Mat result = new Mat();
                    try {
                        Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);
                        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
                        System.out.println(finalI+"    "+ mmr.maxVal);
                        return doubles[finalI] = mmr.maxVal;
                    }finally {
                        result.release();
                    }
                }));
            }

// 获取结果
            double maxScore = futures.stream()
                    .mapToDouble(future -> {
                        try {
                            double db = future.get();
                            return db < similarityMinimum ? 0.0 : db;
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    })
                    .max()
                    .orElse(0.0);
            System.out.println(maxScore);
            if (maxScore == 0.0) {
                return -1;
            } else {
                for (int i = 0; i < doubles.length; i++) {
                    Double aDouble = doubles[i];
                    if (aDouble == maxScore) {
                        return i;
                    }
                }
            }
// 查找最佳匹配的模板
//        for (int i = 0; i < targets.length; i++) {
//            Mat template = targets[i];
//            Mat result = new Mat();
//            Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);
//            Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
//            if (mmr.maxVal == maxScore) {
//                bestMatchScore = mmr.maxVal;
//                bestMatchTemplate = template;
//                break;
//            }
//        }
            return -1;
        }finally {
            executorService.shutdown();
            for (int i = 0; i < targets.length; i++) {
                if (targets[i]!=null)targets[i].release();
            }
        }
    }
    /**
     * 匹配并比对
     *
     * @param src
     * @param targets
     * @return
     */
    public static int matchAndContrast(Mat src,double similarityMinimum, Mat... targets) {
        loadLib();
        Mat outputImage = null;
        try {


            double[] similaritys = new double[targets.length];
            for (int i = 0; i < targets.length; i++) {
                Mat target = targets[i];
                outputImage = new Mat(src.rows(), src.cols(), src.type());
                Imgproc.matchTemplate(src, target, outputImage, Imgproc.TM_CCOEFF_NORMED);

                // 获取匹配结果,查找最大匹配值
                Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
                similaritys[i] = result.maxVal; //匹配度 低于0.9的不要
                System.out.println(result.maxVal);
            }
            double[] numbers = similaritys;
            double max = numbers[0];
            int maxIdx = 0;
            for (int i = 1; i < numbers.length; i++) {
                if (numbers[i] > max) {
                    maxIdx = i;
                    max = numbers[i];
                }
            }
            System.out.println("----");
            if (max < similarityMinimum)//匹配不成功
                return -1;
            return maxIdx;
        } finally {
            if (outputImage != null) {
                outputImage.release();
            }
            for (int i = 0; i < targets.length; i++) {
                targets[i].release();
            }
        }
    }
    public static Mat applyNonMaxSuppression(Mat result, double threshold) {
        int windowSize = 4; // 例如，3x3窗口
        int padding = windowSize / 2;
        Mat resultCopy = new Mat();
        result.copyTo(resultCopy);

        for (int y = padding; y < result.rows() - padding; y++) {
            for (int x = padding; x < result.cols() - padding; x++) {
                double value = resultCopy.get(y, x)[0];
                boolean isMax = true;
                for (int ky = -padding; ky <= padding && isMax; ky++) {
                    for (int kx = -padding; kx <= padding && isMax; kx++) {
                        if (value < resultCopy.get(y + ky, x + kx)[0]) {
                            isMax = false;
                        }
                    }
                }
                if (!isMax || value < threshold) {
                    resultCopy.put(y, x, 0); // 抑制非极大值和低于阈值的值
                }
            }
        }
        return resultCopy;
    }
    public static void circleBorderDetection (Robot robot) throws InterruptedException {
        loadLib();
//        Mat targetImage = Imgcodecs.imread("Z:/Users/adwszzy/Desktop/789.png");
        //        Mat template = Imgcodecs.imread(ConfigConstants.borderPic);
        Mat targetImage =getScreenShot(robot);
        Mat template = Imgcodecs.imread(ConfigConstants.borderPic);


        // 转换到HSV色彩空间
        Mat grayTarget = new Mat();
        Mat grayTemplate = new Mat();
        Imgproc.cvtColor(targetImage, grayTarget, Imgproc.COLOR_BGR2HSV_FULL);
        Imgproc.cvtColor(template, grayTemplate, Imgproc.COLOR_BGR2HSV_FULL);
        Scalar lowerBound = new Scalar(20, 39, 150); // 黄色
        Scalar upperBound = new Scalar(55, 100, 255);
        // 创建掩码
        Mat mask = new Mat();
        Core.inRange(grayTarget, lowerBound, upperBound, mask);
        // 应用掩码
        Mat res = new Mat();
        Core.bitwise_and(targetImage, targetImage, res, mask);


        // 边缘检测
        Mat edgesTarget = new Mat();
        Mat edgesTemplate = new Mat();
        Imgproc.Canny(res, edgesTarget, 50, 150);
        Imgproc.Canny(template, edgesTemplate, 50, 150);

        // 模板匹配
        Mat result = new Mat();
        Imgproc.matchTemplate(edgesTarget, edgesTemplate, result, Imgproc.TM_CCORR_NORMED);

        // 设置阈值
        double threshold = borderSimilarityMinimum;
        // 创建一个与result相同大小和类型的矩阵，并用threshold填充
        // 寻找匹配位置
        Mat resultAfterNMS = applyNonMaxSuppression(result, threshold);
        List<Point> locations = findLocations(resultAfterNMS, threshold);
//        List<Point> locations = findLocations(result, threshold);
        for (Point point : locations) {
            robot.mouseMove((int) (point.x +template.cols()*0.5), (int) (point.y + template.rows()*0.5));
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
            try {
                Thread.sleep(500);
                //匹配声骸并锁定
                matchAndlockTheSoundSkeleton(robot);
                Thread.sleep(200);
                //关闭该页面
                Mat screenMat = getScreenShot(robot);
                Mat template1 = Imgcodecs.imread(ConfigConstants.closePic);
                matchAndPress(template1,screenMat, robot, 0, 0);
                screenMat.release();
                template1.release();
                Thread.sleep(500);


            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        Thread.sleep(250);
        //随便点哪，返回！
        Mat screenMat = getScreenShot(robot);
        Mat template1 = Imgcodecs.imread(ConfigConstants.anywherePic);
        matchAndPress(template1,screenMat, robot, 0, 0);
        screenMat.release();
        template1.release();
        targetImage.release();
        template.release();
        grayTarget.release();
        grayTemplate.release();
        edgesTarget.release();
        edgesTemplate.release();
        // 绘制匹配结果 // 显示结果
//        drawMatches(targetImage,template, locations);
    }
    private static List<double[]> findMatchValues(Mat result, double threshold) {
        Mat thresholdMat = new Mat();
        Core.compare(result, new Scalar(threshold), thresholdMat, Core.CMP_GT);
        MatOfPoint loc = new MatOfPoint();
        Core.findNonZero(thresholdMat, loc);
        Point[] points = loc.toArray();

        List<double[]> matchValues = new ArrayList<>();
        for (Point p : points) {
            double similarity = result.get((int) p.y, (int) p.x)[0];
            matchValues.add(new double[]{p.x, p.y, similarity});
        }
        return matchValues;
    }
    private static List<Point> findLocations(Mat result, double threshold) {
        Mat thresholdMat = new Mat();
        Core.compare(result,new Scalar(threshold), thresholdMat, Core.CMP_GT);
        MatOfPoint loc = new MatOfPoint();
        Core.findNonZero(thresholdMat, loc);
        Point[] points = loc.toArray();
        List<Point> locations = new ArrayList<>();
//        int i = 0;
        for (Point p : points) {
            double similarity = result.get((int) p.y, (int) p.x)[0];
            System.out.println("[debug]point： "+similarity);
            locations.add(p);
        }
        System.out.println("[debug]locations.size()： "+locations.size());
        return locations;
    }

    public static void drawMatches(Mat targetImage, Mat template, List<Point> locations) {
        Mat showPanel = targetImage.clone();
        for (Point location : locations) {
            Point top_left = location;
            Point bottom_right = new Point(location.x + template.cols(), location.y + template.rows());
            Imgproc.rectangle(showPanel, top_left, bottom_right, new Scalar(0, 0, 255), 2);
        }
        HighGui.imshow("模板匹配", showPanel);
        HighGui.waitKey();
    }
    public static Mat bufferedImageToMat(BufferedImage bi) {
        loadLib();
        Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3);
        DataBuffer db = bi.getRaster().getDataBuffer();
        byte[] data = ((DataBufferByte) db).getData();
        mat.put(0, 0, data);
        return mat;
    }
}
